#include "ShopPlayerEvent.h"
#include "EconomyShop.h"
#include "EconomyAPI.h"
#include "Expand/Plugins/AuthPlugin.h"

#include "Log.h"
#include "GameRegistry.hpp"
#include "Player/PlayerData.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentAttacker.h"
#include "Components/ComponentMiner.h"
#include "Components/ComponentOnFire.h"
#include "Components/ComponentBlockEntity.h"
#include "Components/ComponentInventory.h"
#include "Components/ComponentHealth.h"


#include "Network/PackageManager.h"
#include "Network/Packages/MessagePackage.h"
#include "Subsystems/SubsystemTerrain.h"
#include "Blocks/CairnBlock.h"
#include "Blocks/DiamondBlock.h"
#include "Blocks/MatchBlock.h"
#include "Game/BodyRaycastResult.hpp"

namespace Economy
{

    static void sendMessage(ClientPtr client, const std::string & message)
    {
        std::shared_ptr<MessagePackage> package = std::make_shared<MessagePackage>(message);
        package->client = client;
        package->sendType = PackageSendType::TARGET;
        GameSingleton::packageManager->addSendPackageToQueue(package);
    }

    // 放置方块
    bool ShopPlayerEvent::playerPlaceBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t placeBlockValue)
    {
        int32_t contents = Terrain::ExtractContents(placeBlockValue);
        ShopData *shopData = m_economyShop->getShopData(point);
        if (shopData != nullptr)
        {
            uint32_t level = m_economyShop->m_authPlugin->getLevelByGuid(componentPlayer->playerData->playerGuid);
            if (level >= 100)
            {
                if (contents == 210)
                {
                    return true;
                }
                sendMessage(componentPlayer->playerData->client, "请用破坏的方式拆掉商店");
            }
            else
            {
                sendMessage(componentPlayer->playerData->client, "你没有权限破坏商店");
            }
            return false;
        }

        if (contents == 210)
        {
            ShopData newShopData;
            bool findNew = false;

            m_economyShop->m_createShopMutex.lock();
            auto it = m_economyShop->m_createShopPlayer.find(componentPlayer->playerData->playerGuid);
            if (it != m_economyShop->m_createShopPlayer.end())
            {
                newShopData = it->second;
                findNew = true;
                m_economyShop->m_createShopPlayer.erase(it);
            }
            m_economyShop->m_createShopMutex.unlock();

            if (findNew)
            {
                newShopData.point = point;
                m_economyShop->addShop(newShopData);
                if (newShopData.shopType == ShopType::Shop)
                {
                    sendMessage(componentPlayer->playerData->client, fmt::format("成功创建商店，卖：{}，数量：{}，价格：{}", newShopData.value, newShopData.count, newShopData.price));
                }
                else
                {
                    sendMessage(componentPlayer->playerData->client, fmt::format("成功创建回收商店，回收：{}, 数量:{}, 价格：{}", newShopData.value, newShopData.count, newShopData.price));
                }
            }
        }
        return true;
    }

    // 破坏方块
    bool ShopPlayerEvent::playerBreakBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t digBlockValue, int32_t toolLevel)
    {
        int32_t contents = Terrain::ExtractContents(digBlockValue);
        if (contents == 210)
        {
            ShopData *shopData = m_economyShop->getShopData(point);
            if (shopData != nullptr)
            {
                uint32_t level = m_economyShop->m_authPlugin->getLevelByGuid(componentPlayer->playerData->playerGuid);
                if (level >= 100)
                {
                    if (m_economyShop->removeShop(point) == true)
                    {
                        sendMessage(componentPlayer->playerData->client, "成功移除商店");
                    }
                    else
                    {
                        sendMessage(componentPlayer->playerData->client, "发生未知错误");
                    }
                    return true;
                }
                sendMessage(componentPlayer->playerData->client, "你没有权限破坏商店");
                return false;
            }
        }
        return true;
    }

    bool ShopPlayerEvent::playerTouchSign(std::shared_ptr<PlayerData> playerData, const Point3 &point)
    {
        if (playerData->gameMode == GameMode::Creative)
        {
            return true;
        }

        m_economyShop->m_editMutex.lock();
        bool isEdit = (m_economyShop->m_editPlayer.find(playerData->playerGuid) != m_economyShop->m_editPlayer.end());
        m_economyShop->m_editMutex.unlock();

        if (isEdit == false)
        {
            ShopData *shopData = m_economyShop->getShopData(point);
            if (shopData != nullptr)
            {
                if (shopData->shopType == ShopType::Shell)
                {
                    IInventory *inventory = playerData->componentPlayer->componentInventory;
                    uint32_t haveCount = 0;
                    uint32_t shellCount = shopData->count;
                    std::vector<uint32_t> shellSlotIndexVec;

                    for (uint32_t index = 0; index < inventory->slotsCount(); index++)
                    {
                        int32_t slotValue = inventory->getSlotValue(index);
                        if (slotValue == shopData->value)
                        {
                            haveCount += inventory->getSlotCount(index);
                            shellSlotIndexVec.push_back(index);
                        }
                    }
                    if (haveCount >= shellCount)
                    {
                        for (uint32_t index : shellSlotIndexVec)
                        {
                            shellCount -= inventory->removeSlotItems(index, shellCount);
                            if (shellCount <= 0)
                            {
                                m_economyShop->m_economyAPI->addGuidMoney(playerData->playerGuid, shopData->price);
                                sendMessage(playerData->client, fmt::format("成功出售商品，获得 {}$", shopData->price));
                                break;
                            }
                        }
                    }
                    else
                    {
                        sendMessage(playerData->client, "不好意思，你身上的可回收物品不够");
                    }
                }
                else if (shopData->shopType == ShopType::Shop)
                {
                    uint32_t money = m_economyShop->m_economyAPI->getGuidMoney(playerData->playerGuid);
                    if (shopData->price > money)
                    {
                        sendMessage(playerData->client, fmt::format("不好意思，你的钱不够，你需要 {}$ 才能购买该物品", shopData->price));
                    }
                    else
                    {
                        ComponentInventory *inventory = playerData->componentPlayer->componentInventory;
                        uint32_t capacityCount = inventory->getItemCapacityFast(shopData->value);
                        if (capacityCount >= shopData->count)
                        {
                            m_economyShop->m_economyAPI->decGuidMoney(playerData->playerGuid, shopData->price);
                            inventory->addItemFast(shopData->value, shopData->count);
                            sendMessage(playerData->client, fmt::format("成功购买商品，消费 {}$", shopData->price));
                        }
                        else
                        {
                            sendMessage(playerData->client, "你的背包剩余空间不足以存放商品");
                        }
                    }
                }
                return false;
            }
        }
        return true;
    }

    bool ShopPlayerEvent::playerEditSign(std::shared_ptr<PlayerData> playerData, SignTextData &signTextData)
    {
        ShopData *shopData = m_economyShop->getShopData(signTextData.point);
        if (shopData != nullptr)
        {
            uint32_t level = m_economyShop->m_authPlugin->getLevelByGuid(playerData->playerGuid);
            if (level < 100)
            {
                sendMessage(playerData->client, "你没有权限编辑商店");
                Log::Warn(fmt::format("玩家 {} 尝试编辑商店牌子的内容", playerData->username));
                return false;
            }
        }
        return true;
    }

}


